/**
 * Copyright (c) 2020 Coder League
 * All rights reserved.
 *
 * File：SupplierService.java
 * History:
 *         2020年12月27日: Initially created, Chrise.
 */
package club.coderleague.cfss.service.supplier;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import club.coderleague.cfss.config.properties.FileUploadSettings;
import club.coderleague.cfss.dao.AreaDao;
import club.coderleague.cfss.dao.DistributionAreaDao;
import club.coderleague.cfss.dao.OrderDao;
import club.coderleague.cfss.dao.SupplierDao;
import club.coderleague.cfss.dao.SupplierLogDao;
import club.coderleague.cfss.dao.UserDao;
import club.coderleague.cfss.domain.beans.DistributionAreaRequest;
import club.coderleague.cfss.domain.beans.SupplierRegisterRequest;
import club.coderleague.cfss.domain.beans.UserSession;
import club.coderleague.cfss.domain.entities.Distributionareas;
import club.coderleague.cfss.domain.entities.Supplierlogs;
import club.coderleague.cfss.domain.entities.Suppliers;
import club.coderleague.cfss.domain.entities.Users;
import club.coderleague.cfss.domain.enums.EntHandleType;
import club.coderleague.cfss.domain.enums.EntityState;
import club.coderleague.cfss.domain.enums.UserType;
import club.coderleague.cfss.exceptions.FileUploadException;
import club.coderleague.cfss.util.CommonUtil;
import club.coderleague.cfss.util.FileUtil;
import club.coderleague.data.jpa.domain.Page;

/**
 * 供应商服务。
 * @author Chrise
 */
@Service
public class SupplierService {
	private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3456789]\\d{9}$");
	
	@Autowired
	private UserDao userDao;
	@Autowired
	private SupplierDao supplierDao;
	@Autowired
	private SupplierLogDao slDao;
	@Autowired
	private DistributionAreaDao daDao;
	@Autowired
	private OrderDao orderDao;
	@Autowired
	private AreaDao areaDao;
	@Autowired
	private FileUploadSettings fuSettings;
	
	/**
	 * 注册供应商。
	 * @author Chrise 2020年12月27日
	 * @param request 注册请求。
	 * @param buslicense 营业执照。
	 * @param folicense 食品经营许可证。
	 * @param testreport 检测报告。
	 * @param qualityreport 质量报告。
	 * @return 注册结果。
	 */
	public String execRegisterSupplier(SupplierRegisterRequest request, 
		MultipartFile buslicense, MultipartFile folicense, MultipartFile testreport, MultipartFile qualityreport) {
		if (!PHONE_PATTERN.matcher(request.getContactnumber()).matches()) return "无效的联系电话！";
		if (this.supplierDao.existsSupplier(request.getEntname(), request.getBuslicenseno(), null)) return "企业信息已存在！";
		if (this.userDao.existsByLoginnameOrUserphoneNotEntityid(null, request.getContactnumber(), null)) return "无法用联系电话创建账户！";
		
		String buslicensePath = null;
		try {
			buslicensePath = FileUtil.saveFile(buslicense, this.fuSettings.getRootReal() + this.fuSettings.getBuslicensePath(), 
				this.fuSettings.getBuslicenseType(), this.fuSettings.getCommonAttachSize());
		} catch (FileUploadException e) {
			switch (e.getFueCode()) {
				case FILE_INVALID:
					return "营业执照文件无效！";
				case ILLEGAL_TYPE:
					return "营业执照文件类型错误！";
				case TOO_BIG:
					return "营业执照文件太大！";
			}
		} catch (Exception e) {
			return "保存营业执照文件错误！";
		}
		
		String folicensePath = null;
		try {
			folicensePath = FileUtil.saveFile(folicense, this.fuSettings.getRootReal() + this.fuSettings.getFolicensePath(), 
				this.fuSettings.getFolicenseType(), this.fuSettings.getCommonAttachSize());
		} catch (FileUploadException e) {
			switch (e.getFueCode()) {
				case FILE_INVALID:
					return "食品经营许可证文件无效！";
				case ILLEGAL_TYPE:
					return "食品经营许可证文件类型错误！";
				case TOO_BIG:
					return "食品经营许可证文件太大！";
			}
		} catch (Exception e) {
			return "保存食品经营许可证文件错误！";
		}
		
		String testreportPath = null;
		if (testreport != null) {
			try {
				testreportPath = FileUtil.saveFile(testreport, this.fuSettings.getRootReal() + this.fuSettings.getTestreportPath(), 
					this.fuSettings.getTestreportType(), this.fuSettings.getCommonAttachSize());
			} catch (FileUploadException e) {
				switch (e.getFueCode()) {
					case FILE_INVALID:
						return "检测报告文件无效！";
					case ILLEGAL_TYPE:
						return "检测报告文件类型错误！";
					case TOO_BIG:
						return "检测报告文件太大！";
				}
			} catch (Exception e) {
				return "保存检测报告文件错误！";
			}
		}
		
		String qualityreportPath = null;
		if (qualityreport != null) {
			try {
				qualityreportPath = FileUtil.saveFile(qualityreport, this.fuSettings.getRootReal() + this.fuSettings.getQualityreportPath(), 
					this.fuSettings.getQualityreportType(), this.fuSettings.getCommonAttachSize());
			} catch (FileUploadException e) {
				switch (e.getFueCode()) {
					case FILE_INVALID:
						return "质量报告文件无效！";
					case ILLEGAL_TYPE:
						return "质量报告文件类型错误！";
					case TOO_BIG:
						return "质量报告文件太大！";
				}
			} catch (Exception e) {
				return "保存质量报告文件错误！";
			}
		}
		
		Date date = new Date();
		
		Suppliers supplier = new Suppliers(EntityState.AUDITING.getValue(), request.getEntname(), request.getBuslicenseno(), buslicensePath, 
			request.getLeader(), request.getContactnumber(), request.getProvinceid(), request.getCityid(), request.getDistrictid(), request.getStreetid(), 
			request.getDetailaddr(), folicensePath, testreportPath, qualityreportPath, date, null, null);
		this.supplierDao.save(supplier);
		
		Supplierlogs supplierlog = new Supplierlogs(EntityState.VALID.getValue(), supplier.getEntityid(), null, EntHandleType.SUBMIT_DATA.getValue(), date);
		this.slDao.save(supplierlog);
		
		for (DistributionAreaRequest dar : request.getDistributionareas()) {
			Distributionareas distributionarea = this.daDao.queryExistsDistributionArea(supplier.getEntityid(), dar.getProvinceid(), dar.getCityid(), dar.getDistrictid(), dar.getStreetid());
			if (distributionarea == null) {
				distributionarea = new Distributionareas(EntityState.VALID.getValue(), supplier.getEntityid(), dar.getProvinceid(), dar.getCityid(), dar.getDistrictid(), dar.getStreetid());
				this.daDao.save(distributionarea);
			}
		}
		
		Users user = new Users();
		user.setEntitystate(EntityState.VALID.getValue());
		user.setSupplierid(supplier.getEntityid());
		user.setUsertype(UserType.NORMAL.getValue());
		user.setUserphone(supplier.getContactnumber());
		this.userDao.save(user);
		
		return null;
	}
	
	/**
	 * 查询供应商分页数据。
	 * @author Chrise 2020年12月28日
	 * @param states 状态。
	 * @param keyword 关键字。
	 * @param pageIndex 分页索引。
	 * @param pageSize 分页大小。
	 * @return 供应商分页数据。
	 */
	public Page<Map<String, Object>> querySupplierPageData(String states, String keyword, Integer pageIndex, Integer pageSize) {
		List<Integer> list = new ArrayList<Integer>();
		if (CommonUtil.isEmpty(states)) {
			list.add(EntityState.AUDITING.getValue());
			list.add(EntityState.OPENING.getValue());
		} else {
			String[] array = states.split(",");
			for (String s : array) {
				list.add(Integer.valueOf(s));
			}
		}
		
		String buslicensePath = this.fuSettings.getRootVirtual() + this.fuSettings.getBuslicensePath();
		String folicensePath = this.fuSettings.getRootVirtual() + this.fuSettings.getFolicensePath();
		String testreportPath = this.fuSettings.getRootVirtual() + this.fuSettings.getTestreportPath();
		String qualityreportPath = this.fuSettings.getRootVirtual() + this.fuSettings.getQualityreportPath();
		
		return this.supplierDao.querySupplierPageData(list, keyword, 
			buslicensePath, folicensePath, testreportPath, qualityreportPath, pageIndex, pageSize);
	}
	
	/**
	 * 修改供应商状态。
	 * @author Chrise 2020年12月29日
	 * @param entityids 实体标识。
	 * @param state 实体状态。
	 * @param us 用户会话。
	 */
	public void updateState(String entityids, int state, UserSession us) {
		Date date = new Date();
		String[] array = entityids.split(",");
		for (String entityid : array) {
			Suppliers supplier = this.supplierDao.getOne(Long.valueOf(entityid));
			supplier.setEntitystate(state);
			supplier.setAuditor(us.getId());
			supplier.setAudittime(date);
			
			Supplierlogs log = new Supplierlogs(EntityState.VALID.getValue(), supplier.getEntityid(), us.getId(), EntHandleType.AUDIT_DATA.getValue(), date);
			this.slDao.save(log);
		}
	}
	
	/**
	 * 查询配送区域只读数据。
	 * @author Chrise 2020年12月29日
	 * @param entityid 实体标识。
	 * @return 配送区域只读数据。
	 */
	public List<Map<String, Object>> queryDistributionArea(long entityid) {
		return this.daDao.queryDistributionArea(entityid);
	}
	
	/**
	 * 查询供应商详情数据。
	 * @author Chrise 2020年12月29日
	 * @param entityid 实体标识。
	 * @return 供应商详情数据。
	 */
	public Map<String, Object> querySupplierDetail(long entityid) {
		String buslicensePath = this.fuSettings.getRootVirtual() + this.fuSettings.getBuslicensePath();
		String folicensePath = this.fuSettings.getRootVirtual() + this.fuSettings.getFolicensePath();
		String testreportPath = this.fuSettings.getRootVirtual() + this.fuSettings.getTestreportPath();
		String qualityreportPath = this.fuSettings.getRootVirtual() + this.fuSettings.getQualityreportPath();
		
		Map<String, Object> supplier = this.supplierDao.querySupplierDetail(entityid, buslicensePath, folicensePath, testreportPath, qualityreportPath);
		supplier.put("areas", this.daDao.queryDistributionArea(entityid));
		return supplier;
	}
	
	/**
	 * 检查供应商状态。
	 * @author Chrise 2021年1月10日
	 * @param session 用户会话。
	 * @return 检查结果。
	 */
	public Map<String, Object> checkSupplierState(UserSession session) {
		Integer state = this.supplierDao.querySupplierState(session.getOrgid());
		if (state == null || EntityState.DELETED.equalsValue(state)) return null;
		
		int orderNumber = this.orderDao.queryHandlingNumber(session.getOrgid(), true);
		
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("supplierState", EntityState.OPENING.equalsValue(state));
		result.put("orderNumber", orderNumber);
		return result;
	}
	
	/**
	 * 加载个人信息。
	 * @author Chrise 2021年2月9日
	 * @param session 用户会话。
	 * @return 个人信息。
	 */
	public Map<String, Object> loadPersonalInfo(UserSession session) {
		Map<String, Object> supplier = this.supplierDao.queryPersonalInfo(session.getOrgid());
		
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("supplier", supplier);
		return result;
	}
	
	/**
	 * 加载供应商数据。
	 * @author Chrise 2021年2月7日
	 * @param session 用户会话。
	 * @return 供应商数据。
	 */
	public Map<String, Object> loadSupplierData(UserSession session) {
		String buslicensePath = this.fuSettings.getRootVirtual() + this.fuSettings.getBuslicensePath();
		String folicensePath = this.fuSettings.getRootVirtual() + this.fuSettings.getFolicensePath();
		String testreportPath = this.fuSettings.getRootVirtual() + this.fuSettings.getTestreportPath();
		String qualityreportPath = this.fuSettings.getRootVirtual() + this.fuSettings.getQualityreportPath();
		
		Map<String, Object> supplier = this.supplierDao.querySupplierData(session.getOrgid(), buslicensePath, folicensePath, testreportPath, qualityreportPath);
		List<Map<String, Object>> dareas = this.daDao.queryDistributionAreaData(session.getOrgid());
		
		Map<String, List<Map<String, Object>>> areas = new HashMap<String, List<Map<String,Object>>>();
		areas.put("0", this.areaDao.getAreasForMobileSelect(null));
		
		Long provinceid = (Long)supplier.get("provinceid");
		areas.put(provinceid.toString(), this.areaDao.getAreasForMobileSelect(provinceid));
		Long cityid = (Long)supplier.get("cityid");
		areas.put(cityid.toString(), this.areaDao.getAreasForMobileSelect(cityid));
		Long districtid = (Long)supplier.get("districtid");
		areas.put(districtid.toString(), this.areaDao.getAreasForMobileSelect(districtid));
		
		for (Map<String, Object> darea : dareas) {
			Long dprovinceid = (Long)darea.get("provinceid");
			String sprovinceid = dprovinceid.toString();
			if (!areas.containsKey(sprovinceid)) areas.put(sprovinceid, this.areaDao.getAreasForMobileSelect(dprovinceid));
			
			Long dcityid = (Long)darea.get("cityid");
			String scityid = dcityid.toString();
			if (!areas.containsKey(scityid)) areas.put(scityid, this.areaDao.getAreasForMobileSelect(dcityid));
			
			Long ddistrictid = (Long)darea.get("districtid");
			String sdistrictid = ddistrictid.toString();
			if (!areas.containsKey(sdistrictid)) areas.put(sdistrictid, this.areaDao.getAreasForMobileSelect(ddistrictid));
		}
		
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("supplier", supplier);
		result.put("dareas", dareas);
		result.put("areas", areas);
		return result;
	}
	
	/**
	 * 重新提交供应商。
	 * @author Chrise 2021年2月9日
	 * @param request 注册请求。
	 * @param buslicense 营业执照。
	 * @param folicense 食品经营许可证。
	 * @param testreport 检测报告。
	 * @param qualityreport 质量报告。
	 * @param session 用户会话。
	 * @return 提交结果。
	 */
	public String execResubmitSupplier(SupplierRegisterRequest request, 
		MultipartFile buslicense, MultipartFile folicense, MultipartFile testreport, MultipartFile qualityreport, UserSession session) {
		if (!PHONE_PATTERN.matcher(request.getContactnumber()).matches()) return "无效的联系电话！";
		if (this.supplierDao.existsSupplier(request.getEntname(), request.getBuslicenseno(), session.getOrgid())) return "企业信息已存在！";
		
		String buslicensePath = null;
		if (buslicense != null) {
			try {
				buslicensePath = FileUtil.saveFile(buslicense, this.fuSettings.getRootReal() + this.fuSettings.getBuslicensePath(), 
					this.fuSettings.getBuslicenseType(), this.fuSettings.getCommonAttachSize());
			} catch (FileUploadException e) {
				switch (e.getFueCode()) {
					case FILE_INVALID:
						return "营业执照文件无效！";
					case ILLEGAL_TYPE:
						return "营业执照文件类型错误！";
					case TOO_BIG:
						return "营业执照文件太大！";
				}
			} catch (Exception e) {
				return "保存营业执照文件错误！";
			}
		}
		
		String folicensePath = null;
		if (folicense != null) {
			try {
				folicensePath = FileUtil.saveFile(folicense, this.fuSettings.getRootReal() + this.fuSettings.getFolicensePath(), 
					this.fuSettings.getFolicenseType(), this.fuSettings.getCommonAttachSize());
			} catch (FileUploadException e) {
				switch (e.getFueCode()) {
					case FILE_INVALID:
						return "食品经营许可证文件无效！";
					case ILLEGAL_TYPE:
						return "食品经营许可证文件类型错误！";
					case TOO_BIG:
						return "食品经营许可证文件太大！";
				}
			} catch (Exception e) {
				return "保存食品经营许可证文件错误！";
			}
		}
		
		String testreportPath = null;
		if (testreport != null) {
			try {
				testreportPath = FileUtil.saveFile(testreport, this.fuSettings.getRootReal() + this.fuSettings.getTestreportPath(), 
					this.fuSettings.getTestreportType(), this.fuSettings.getCommonAttachSize());
			} catch (FileUploadException e) {
				switch (e.getFueCode()) {
					case FILE_INVALID:
						return "检测报告文件无效！";
					case ILLEGAL_TYPE:
						return "检测报告文件类型错误！";
					case TOO_BIG:
						return "检测报告文件太大！";
				}
			} catch (Exception e) {
				return "保存检测报告文件错误！";
			}
		}
		
		String qualityreportPath = null;
		if (qualityreport != null) {
			try {
				qualityreportPath = FileUtil.saveFile(qualityreport, this.fuSettings.getRootReal() + this.fuSettings.getQualityreportPath(), 
					this.fuSettings.getQualityreportType(), this.fuSettings.getCommonAttachSize());
			} catch (FileUploadException e) {
				switch (e.getFueCode()) {
					case FILE_INVALID:
						return "质量报告文件无效！";
					case ILLEGAL_TYPE:
						return "质量报告文件类型错误！";
					case TOO_BIG:
						return "质量报告文件太大！";
				}
			} catch (Exception e) {
				return "保存质量报告文件错误！";
			}
		}
		
		Date date = new Date();
		
		Suppliers supplier = this.supplierDao.getOne(session.getOrgid());
		supplier.setEntname(request.getEntname());
		supplier.setBuslicenseno(request.getBuslicenseno());
		supplier.setLeader(request.getLeader());
		supplier.setContactnumber(request.getContactnumber());
		supplier.setProvinceid(request.getProvinceid());
		supplier.setCityid(request.getCityid());
		supplier.setDistrictid(request.getDistrictid());
		supplier.setStreetid(request.getStreetid());
		supplier.setDetailaddr(request.getDetailaddr());
		supplier.setEntitystate(EntityState.AUDITING.getValue());
		supplier.setApplytime(date);
		if (buslicensePath != null) supplier.setBuslicense(buslicensePath);
		if (folicensePath != null) supplier.setFolicense(folicensePath);
		if (testreportPath != null) supplier.setTestreport(testreportPath);
		if (qualityreportPath != null) supplier.setQualityreport(qualityreportPath);
		
		Supplierlogs supplierlog = new Supplierlogs(EntityState.VALID.getValue(), supplier.getEntityid(), session.getId(), EntHandleType.SUBMIT_DATA.getValue(), date);
		this.slDao.save(supplierlog);
		
		for (DistributionAreaRequest dar : request.getDistributionareas()) {
			if (dar.getEntityid() == null) {
				Distributionareas distributionarea = this.daDao.queryExistsDistributionArea(supplier.getEntityid(), dar.getProvinceid(), dar.getCityid(), dar.getDistrictid(), dar.getStreetid());
				if (distributionarea == null) {
					distributionarea = new Distributionareas(EntityState.VALID.getValue(), supplier.getEntityid(), dar.getProvinceid(), dar.getCityid(), dar.getDistrictid(), dar.getStreetid());
					this.daDao.save(distributionarea);
				} else distributionarea.setEntitystate(EntityState.VALID.getValue());
			} else {
				Distributionareas distributionarea = this.daDao.getOne(dar.getEntityid());
				if (dar.getDeleteflag()) distributionarea.setEntitystate(EntityState.INVALID.getValue());
				else {
					distributionarea.setProvinceid(dar.getProvinceid());
					distributionarea.setCityid(dar.getCityid());
					distributionarea.setDistrictid(dar.getDistrictid());
					distributionarea.setStreetid(dar.getStreetid());
				}
			}
		}
		
		return null;
	}
}
